package com.vecspace.utils;

import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;

import comvecspace.data.model.sql.MinDataType;

public class SqlUtil {
	/**
	 * 过滤sql中的特殊字符，一般对于客户端传入的相关sql如查询值、字段名等要做过滤处理
	 * @param sql
	 * @return 
	 * @author: wanghua
	 */
	public static String SqlCharFilter(String source){
		//单引号替换成两个单引号
        //source = source.replace("'", "''");
        while(source.contains("--")){
        	source = source.replace("--", "-");
        }
        //半角封号替换为全角封号，防止多语句执行
        source = source.replace(";", " ");
  
        //去除执行存储过程的命令关键字
        source = source.replace("Exec", "");
        source = source.replace("Execute", "");

        //去除系统存储过程或扩展存储过程关键字
        source = source.replace("xp_", "x p_");
        source = source.replace("sp_", "s p_");

        //防止16进制注入
        source = source.replace("0x", "0 x");

        //防止16进制注入
        source = source.replace("%u", "% u");
        return source;
	}
	/**
	 * 判断SQL名称是否合法，比如表名，字段名
	 * @author: wanghua
	 */
	public static boolean isValidSqlDML(String dml){
		if(dml == null || dml.length() ==0 || dml.contains("--")) {
			return false;
		}
		
		for(int i=0,n=dml.length();i<n;++i){
			boolean valid = false;
			char ch = dml.charAt(i);
			if(ch == '_' || ch == ' ' || ch == '.' || ch == '(' || ch == ')' || ch == '+' || ch == '-' || ch == '*' || ch == '/') {
				valid = true; //字段允许空格 比如  name as username
			}
			else if(ch >='a' && ch <= 'z') {
				valid = true;
			}
			else if(ch >='A' && ch <= 'Z') {
				valid = true;
			}
			else if(ch >='0' && ch <= '9') {
				valid = true;
			}
			if(!valid) {
				return false;
			}
		}
		return true;
	}
	/**判断sqlType是否是字符串类型
	 * 
	 * @param sqlType sqlType是java.sql.Types的一个值
	 * @return
	 * @author: wanghua
	 */
	public static boolean isVarcharColumn(int sqlType){
		if(sqlType == Types.VARCHAR) {
			return true;
		}
		if(sqlType == Types.NVARCHAR) {
			return true;
		}
		if(sqlType == Types.CHAR) {
			return true;
		}
		if(sqlType == Types.LONGNVARCHAR) {
			return true;
		}
		if(sqlType == Types.LONGVARCHAR) {
			return true;
		}
		if(sqlType == Types.NCHAR) {
			return true;		
		}
		return false;
	}
	
	/**判断sqlType是否是一个整数类型（包括Short，Integer，Long等）
	 * 
	 * @param sqlType sqlType sqlType是java.sql.Types的一个值
	 * @return
	 * @author: wanghua
	 */
	public static boolean isIntegerColumn(int sqlType){
		if(sqlType == Types.INTEGER) {
			return true;
		}
		if(sqlType == Types.SMALLINT) {
			return true;
		}
		if(sqlType == Types.TINYINT) {
			return true;
		}
		if(sqlType == Types.BIT) {
			return true;
		}
		if(sqlType == Types.BIGINT) {
			return true;		
		}
		return false;
	}
	

	/**判断sqlType是否是一个数字类型（包括所有数字类型）
	 * 
	 * @param sqlType sqlType sqlType是java.sql.Types的一个值
	 * @return
	 * @author: wanghua
	 */
	public static boolean isNumricColumn(int sqlType){
		if(sqlType == Types.INTEGER) {
			return true;
		}
		if(sqlType == Types.SMALLINT) {
			return true;
		}
		if(sqlType == Types.TINYINT) {
			return true;
		}
		if(sqlType == Types.BIT) {
			return true;
		}
		if(sqlType == Types.BIGINT) {
			return true;
		}
		if(sqlType == Types.DECIMAL) {
			return true;
		}
		if(sqlType == Types.DOUBLE) {
			return true;
		}
		if(sqlType == Types.FLOAT) {
			return true;
		}
		if(sqlType == Types.NUMERIC) {
			return true;
		}
		if(sqlType == Types.REAL) {
			return true;		
		}
		return false;
	}
	
	/**判断sqlType是否是一个日期类型（包括纯日期以及日期时间格式）
	 * 
	 * @param sqlType sqlType sqlType是java.sql.Types的一个值
	 * @return
	 * @author: wanghua
	 */
	public static boolean isDateTimeColumn(int sqlType){
		if(sqlType == Types.DATE) {
			return true;
		}
		if(sqlType == Types.TIME) {
			return true;
		}
		if(sqlType == Types.TIMESTAMP) {
			return true;		
		}
		return false;
	}
	
	/**判断sqlType是否是Clob类型
	 * 
	 * @param sqlType sqlType sqlType是java.sql.Types的一个值
	 * @return
	 * @author: wanghua
	 */
	public static boolean isClobColumn(int sqlType){
		if(sqlType == Types.CLOB) {
			return true;
		}
		if(sqlType == Types.NCLOB) {
			return true;
		}
		return false;
	}
	
	/**将date转为Timestamp对象。如果date为null，直接返回null。
	 * @param date
	 * @return
	 * @author: wanghua
	 */
	public static Timestamp toSqlDateTime(java.util.Date date) {
		if(date == null)return null;
		else return new Timestamp(date.getTime());
	}
	
	/**Constructs a Timestamp object using a milliseconds time value
	 * 
	 * @param times
	 * @return 
	 * @author: wanghua
	 */
	public static Timestamp toSqlDateTime(long times) {
		return new Timestamp(times);
	}
	
	/**将两个数组合并为一个数组
	 * @param params1
	 * @param params2
	 * @return 
	 * @author: wanghua
	 */
	public static Object[] joinParams(Object[] params1, Object... params2) {
		if(params1 == null || params1.length == 0)return params2;
		if(params2 == null || params2.length == 0)return params1;
		List<Object> list = new ArrayList<>();
		for(Object obj : params1) {
			list.add(obj);
		}
		for(Object obj : params2) {
			list.add(obj);
		}
		return list.toArray();
	}
	
	/**将java.sql.Types转为MinDataType
	 * 
	 * @param sqlType java.sql.Types
	 * @return 
	 * @author: wanghua
	 */
	public static MinDataType parseSqlType(int sqlType) {
		MinDataType dataType = MinDataType.String;
		switch(sqlType) {
			case java.sql.Types.BIGINT:
			case java.sql.Types.BIT:
			case java.sql.Types.INTEGER:
			case java.sql.Types.SMALLINT:	
			case java.sql.Types.TINYINT:		
				dataType = MinDataType.Int;
				break;
			case java.sql.Types.DECIMAL:
			case java.sql.Types.DOUBLE:
			case java.sql.Types.FLOAT:
			case java.sql.Types.REAL:
			case java.sql.Types.NUMERIC:
				dataType = MinDataType.Float;
				break;
				
			case java.sql.Types.DATE:
			case java.sql.Types.TIME:
			case java.sql.Types.TIMESTAMP:
			case java.sql.Types.TIME_WITH_TIMEZONE:
			case java.sql.Types.TIMESTAMP_WITH_TIMEZONE:
				dataType = MinDataType.Date;
				break;
			case java.sql.Types.CLOB:
			case java.sql.Types.LONGNVARCHAR:
			case java.sql.Types.LONGVARCHAR:
				dataType = MinDataType.Clob;
				break;
			case java.sql.Types.ARRAY:
			case java.sql.Types.BLOB:
			case java.sql.Types.JAVA_OBJECT:
			case java.sql.Types.LONGVARBINARY:
			case java.sql.Types.OTHER:
			case java.sql.Types.STRUCT:
				dataType = MinDataType.Blob;
				break;
		}
		return dataType;
	}
	
}
